package com.google.code.coma.space;

import com.google.code.coma.domain.Computer;
import com.google.code.coma.domain.LifeCycleStep;
import com.google.code.coma.domain.Order;
import com.sun.org.apache.xpath.internal.operations.Or;
import org.mozartspaces.capi3.Capi3Exception;
import org.mozartspaces.capi3.CountNotMetException;
import org.mozartspaces.capi3.javanative.operation.NativeEntry;

import java.util.*;

/**
 * Callback for searching a computer with a given state (LifeCycleStep)
 *
 * @author Bernhard Nickel, e0925384@student.tuwien.ac.at
 */
public class ComputerSelectorCallback implements SelectorCallback {
	private List<LifeCycleStep> lifeCycleSteps;
    private Order order;

	public ComputerSelectorCallback(LifeCycleStep... lifeCycleSteps) {
		this.lifeCycleSteps = Arrays.asList(lifeCycleSteps);
	}

    public ComputerSelectorCallback(Order order, LifeCycleStep... lifeCycleSteps) {
        this(lifeCycleSteps);
        this.order = order;
    }

	@Override
	public List<NativeEntry> doInTransaction(Collection<NativeEntry> coordinatorCollection, CallContext callContext) throws Capi3Exception {
        if (order != null) {
            return selectByOrderAndLifeCycleStep(coordinatorCollection, callContext);
        }

        return selectByLifeCycleStep(coordinatorCollection, callContext);
	}

    public List<NativeEntry> selectByLifeCycleStep(Collection<NativeEntry> coordinatorCollection, CallContext callContext) throws Capi3Exception {

		for (NativeEntry entry : coordinatorCollection) {
			if (entry.getData() instanceof Computer) {
				Computer computer = (Computer) entry.getData();

				if (lifeCycleSteps.contains(computer.getCurrent())) {
					return Collections.singletonList(entry);
				}
			}
		}

		throw new CountNotMetException(SpaceSelector.SELECTOR_NAME, 0, 0);
	}

    public List<NativeEntry> selectByOrderAndLifeCycleStep(Collection<NativeEntry> coordinatorCollection, CallContext callContext) throws Capi3Exception {
        List<NativeEntry> entries = new ArrayList<NativeEntry>();

		for (NativeEntry entry : coordinatorCollection) {
			if (entry.getData() instanceof Computer) {
				Computer computer = (Computer) entry.getData();

				if (computer.getOrder() != null && computer.getOrder().getId().equals(order.getId()) && lifeCycleSteps.contains(computer.getCurrent())) {
					entries.add(entry);
				}
			}
		}

		return entries;
	}
}
